package com.xiaoq.ar.endpoint2C;

import com.xiaoq.ar.entity.ARActivityEntity;
import com.xiaoq.ar.entity.MyTreasureEntity;
import com.xiaoq.ar.entity.Punchs;
import com.xiaoq.ar.entity.TreasureSpot;
import com.xiaoq.ar.service.ARActivityService;
import com.xiaoq.ar.service.MyTreasureService;
import com.xiaoq.ar.vo.*;
import com.xiaoq.coms.GenericDataResponse;
import com.xiaoq.coms.GenericListResponse;
import com.xiaoq.coms.GenericResponse;
import com.xiaoq.coms.util.IdGenerator;
import com.xiaoq.feature.entity.ShopFoodEntity;
import com.xiaoq.feature.service.IShopFoodService;
import com.xiaoq.qiniu.QiNiuSpaceEnum;
import com.xiaoq.qiniu.UploadUtil;
import com.xiaoq.sites.entity.SitesEntity;
import com.xiaoq.sites.entity.SitesPointEntity;
import com.xiaoq.sites.service.ISitesService;
import com.xiaoq.sites.vo.SearchResultVo;
import com.xiaoq.vo.PagingVo;
import io.swagger.annotations.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.*;

/**
 * Created by chenjh on 2018/3/5.
 */
@Api(tags = "AR寻宝")
@RestController
@RequestMapping("/api/v1/ar")
public class ARActivityEndPoint2C {

    private Logger logger = LoggerFactory.getLogger(ARActivityEndPoint2C.class);
    private static final class ARActivityVoResponse extends GenericDataResponse<ARActivityVo> {}
    private static final class MyTreasureStatisVoResponse extends GenericDataResponse<MyTreasureStatisVo> {}
    private static final class MyTreasureResponse extends GenericListResponse<MyTreasureVo> {}
    private static final class NearAreaResponse extends GenericListResponse<NearAreaVo> {}
    private static final class SearchResultResponse extends GenericListResponse<SearchResultVo> {}


    @Autowired
    private IShopFoodService shopFoodService;

    @Autowired
    private ARActivityService arActivityService;

    @Autowired
    private MyTreasureService myTreasureService;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private ISitesService sitesService;

    @ApiOperation(value="判断AR寻宝是否存在", notes="判断AR寻宝是否存在")
    @ApiResponses({
            @ApiResponse(code = 200, response = ARActivityVoResponse.class, message = "判断AR寻宝是否存在")
    })
    @GetMapping(value="/{shopId}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> getByArActivityId(@PathVariable("shopId") @ApiParam(value="shopId", required=true) String shopId,
                                               HttpServletRequest request) {

        String userId = (String)request.getAttribute("userId");
        ARActivityEntity arActivityEntity = arActivityService.getLatestByProviderId(shopId);
        ARActivityVo arActivityVo = new ARActivityVo();
        String arActivityId = "";
        arActivityVo.setTreasureSpotList(new ArrayList<>());
        if(arActivityEntity != null){

            arActivityId = arActivityEntity.getId();
            BeanUtils.copyProperties(arActivityEntity, arActivityVo, "treasureSpotList");
            if(arActivityEntity.getTreasureSpotList() != null){
                for(TreasureSpot treasureSpot : arActivityEntity.getTreasureSpotList()){
                    TreasureSpotVO treasureSpotVo = new TreasureSpotVO();
                    BeanUtils.copyProperties(treasureSpot, treasureSpotVo);
                    arActivityVo.getTreasureSpotList().add(treasureSpotVo);
                }
            }
            long currentMillis = System.currentTimeMillis();
            if(arActivityEntity.getStartTime()<currentMillis
                    && arActivityEntity.getEndTime()>currentMillis){
                arActivityVo.setExist(true);
            }else {
                arActivityVo.setExist(false);
            }
        }else {
            arActivityVo.setExist(false);
        }

        if(!arActivityVo.isExist()){
            return ARActivityVoResponse.okWithData(arActivityVo);
        }

        MyTreasureEntity myTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
        List<Punchs> punchsList;
        Map<String, Punchs> treasureSpotId2PunchsMap = new HashMap<>(); //已打卡的藏宝点集合
        if(myTreasureEntity!=null && CollectionUtils.isNotEmpty(punchsList = myTreasureEntity.getPunchsList())){
            for(Punchs punchs : punchsList){
                treasureSpotId2PunchsMap.put(punchs.getTreasureSpotId(), punchs);
            }

            if(myTreasureEntity.getExchangeTime() != null){
                arActivityVo.setExchange(true);  //设置已兑换
            }
        }

        List<TreasureSpotVO> treasureSpotList = arActivityVo.getTreasureSpotList();
        if(CollectionUtils.isNotEmpty(treasureSpotList)){
            int totalCount = treasureSpotList.size();
            int hasNum = treasureSpotId2PunchsMap.size();
            int remainCount = totalCount - hasNum;
            //宝物的总数量
            arActivityVo.setTreasureCount(totalCount);
            //还需捕获的数量
            arActivityVo.setRemainNum(remainCount);
            arActivityVo.setHasNum(hasNum);

            for(TreasureSpotVO treasureSpotVo : treasureSpotList){
                String treasureSpotId = treasureSpotVo.getId();
                Punchs punchs = null;
                if((punchs = treasureSpotId2PunchsMap.get(treasureSpotId)) != null ){
                    treasureSpotVo.setSign(1);//设置为已打卡
                    treasureSpotVo.setPhotoUrl(punchs.getPhotoUrl());  //设置打卡图片
                }
            }
        }

        return ARActivityVoResponse.okWithData(arActivityVo);
    }


    @ApiOperation(value="我的宝物", notes="我的宝物")
    @ApiResponses({
            @ApiResponse(code = 200, response = ARActivityVoResponse.class, message = "我的宝物")
    })
    @GetMapping(value="/{arActivityId}/mytreasure", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> beginGoActivity(@PathVariable("arActivityId") @ApiParam(value="arActivityId", required=true) String arActivityId,
                                             HttpServletRequest request) {
        String userId = (String)request.getAttribute("userId");

        ARActivityEntity arActivityEntity = arActivityService.getByPrimaryId(arActivityId);
        ARActivityVo arActivityVo = new ARActivityVo();

        arActivityVo.setTreasureSpotList(new ArrayList<>());
        if(arActivityEntity != null){
            BeanUtils.copyProperties(arActivityEntity, arActivityVo, "treasureSpotList");
            if(arActivityEntity.getTreasureSpotList() != null){
                for(TreasureSpot treasureSpot : arActivityEntity.getTreasureSpotList()){
                    TreasureSpotVO treasureSpotVo = new TreasureSpotVO();
                    BeanUtils.copyProperties(treasureSpot, treasureSpotVo);
                    arActivityVo.getTreasureSpotList().add(treasureSpotVo);
                }
            }
        }

        MyTreasureEntity myTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
        List<Punchs> punchsList;
        Map<String, Punchs> treasureSpotId2PunchsMap = new HashMap<>(); //已打卡的藏宝点集合
        if(myTreasureEntity!=null && CollectionUtils.isNotEmpty(punchsList = myTreasureEntity.getPunchsList())){
            for(Punchs punchs : punchsList){
                treasureSpotId2PunchsMap.put(punchs.getTreasureSpotId(), punchs);
            }

            if(myTreasureEntity.getExchangeTime() != null){
                arActivityVo.setExchange(true);  //设置已兑换
            }
        }

        List<TreasureSpotVO> treasureSpotList = arActivityVo.getTreasureSpotList();
        if(CollectionUtils.isNotEmpty(treasureSpotList)){
            int totalCount = treasureSpotList.size();
            int hasNum = treasureSpotId2PunchsMap.size();
            int remainCount = totalCount - hasNum;
            //宝物的总数量
            arActivityVo.setTreasureCount(totalCount);
            //还需捕获的数量
            arActivityVo.setRemainNum(remainCount);
            arActivityVo.setHasNum(hasNum);

            for(TreasureSpotVO treasureSpotVo : treasureSpotList){
                String treasureSpotId = treasureSpotVo.getId();
                Punchs punchs = null;
                if((punchs = treasureSpotId2PunchsMap.get(treasureSpotId)) != null ){
                    treasureSpotVo.setSign(1);//设置为已打卡
                    treasureSpotVo.setPhotoUrl(punchs.getPhotoUrl());  //设置打卡图片
                }
            }
        }

        return ARActivityVoResponse.okWithData(arActivityVo);
    }


/*    @ApiOperation(value="我的宝物", notes="我的宝物")
    @ApiResponses({
            @ApiResponse(code = 200, response = MyTreasureStatisVoResponse.class, message = "我的宝物")
    })
    @GetMapping(value="/{arActivityId}/mytreasure/statis", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> myTreasureStatis(@PathVariable("arActivityId") @ApiParam(value="arActivityId", required=true) String arActivityId,
                                              HttpServletRequest request) {

        String userId = (String)request.getAttribute("userId");
        MyTreasureEntity myTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
        MyTreasureStatisVo myTreasureStatisVo = new MyTreasureStatisVo();
        if(myTreasureEntity == null){
            myTreasureEntity = new MyTreasureEntity();
        }
        List<Punchs> punchsList = myTreasureEntity.getPunchsList();

        ARActivityEntity arActivityEntity = arActivityService.getByPrimaryId(arActivityId);
        if(arActivityEntity == null){
            return MyTreasureStatisVoResponse.ng("活动不存在");
        }
        List<TreasureSpot> treasureSpotList = arActivityEntity.getTreasureSpotList();

        long totalNum = treasureSpotList==null?0L:treasureSpotList.size();
        long hasNum = punchsList==null?0L:punchsList.size();
        long remainNum = totalNum - hasNum;
        myTreasureStatisVo.setHasNum(hasNum);
        myTreasureStatisVo.setRemainNum(remainNum);
        myTreasureStatisVo.setTreasureImg(arActivityEntity.getTreasureImg());

        return MyTreasureStatisVoResponse.okWithData(myTreasureStatisVo);
    }*/

    @ApiOperation(value="兑换奖品", notes="兑换奖品")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenericResponse.class, message = "兑换奖品")
    })
    @PostMapping(value="/{arActivityId}/exchange", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> exchangeTreasure(@PathVariable("arActivityId") @ApiParam(value="arActivityId", required=true) String arActivityId,
                                              HttpServletRequest request) {

        String userId = (String)request.getAttribute("userId");
        ARActivityEntity arActivityEntity = arActivityService.getByPrimaryId(arActivityId);
        List<TreasureSpot> treasureSpotList;
        if(arActivityEntity==null || CollectionUtils.isEmpty(treasureSpotList=arActivityEntity.getTreasureSpotList())){
            return GenericResponse.ng("活动不存在");
        }
        MyTreasureEntity myTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
        List<Punchs> punchsList;
        if(myTreasureEntity==null || CollectionUtils.isEmpty(punchsList=myTreasureEntity.getPunchsList())){
            return GenericResponse.ng("此用户未打卡");
        }
        long totalCount = treasureSpotList.size();
        long hasCount = punchsList.size();
        if(hasCount<totalCount && totalCount>0){
            return GenericResponse.ng("还有部分景点未打卡");
        }

        MyTreasureEntity updateMyTreasure = new MyTreasureEntity();
        updateMyTreasure.setId(myTreasureEntity.getId());
        updateMyTreasure.setExchange(true);
        long currentMillis = System.currentTimeMillis();
        updateMyTreasure.setExchangeTime(currentMillis);
        updateMyTreasure.setUpdatedAt(currentMillis);
        boolean flag = myTreasureService.updateMyTreasureById(updateMyTreasure);
        if(flag){
            return GenericResponse.ok();
        }
        return GenericResponse.ng("更新数据库记录失败");
    }

    @ApiOperation(value="添加打卡记录", notes="添加打卡记录")
    @ApiResponses({
            @ApiResponse(code = 200, response = MyTreasureStatisVoResponse.class, message = "添加打卡记录")
    })
    @PostMapping(value="/{arActivityId}/punchs", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> addPunchs(@PathVariable("arActivityId") @ApiParam(value="arActivityId", required=true) String arActivityId,
                                       HttpServletRequest request,
                                       @ModelAttribute(value = "punchsVo") @ApiParam(value = "punchsVo", required = true)PunchsVo punchsVo,
                                       @RequestParam(value = "file", required = true) @ApiParam(value = "图片", required = true) MultipartFile file) {
        if(punchsVo==null || punchsVo.getLatitude()==null || punchsVo.getLongitude()==null
                || StringUtils.isBlank(punchsVo.getTreasureSpotId())){
            return GenericResponse.ng("RequestBody 不能为空");
        }

        String userId = (String) request.getAttribute("userId");
        String imgUrl = "";
        try {
            if (file != null && file.getSize()>0) {
                imgUrl = UploadUtil.easyUploadByte(file, QiNiuSpaceEnum.XIAOQ_SITES.getName().toLowerCase(),
                        QiNiuSpaceEnum.XIAOQ_SITES.getDomain());
            }else {
                return GenericResponse.ng("上传的图片为空");
            }
        } catch (Exception e) {
            logger.error("七牛云上传异常！", e);
            return GenericResponse.ng("图片上传失败！");
        }
        if(StringUtils.isBlank(imgUrl)){
            return GenericResponse.ng("1图片上传失败！");
        }

        ARActivityEntity arActivityEntity = arActivityService.getByPrimaryId(arActivityId);
        List<TreasureSpot> treasureSpotList;
        if(arActivityEntity==null || CollectionUtils.isEmpty(treasureSpotList=arActivityEntity.getTreasureSpotList())){
            return GenericResponse.ng("活动不存在");
        }

        Map<String, TreasureSpot> spotId2SpotMap = new HashMap<>();
        for(TreasureSpot treasureSpot : treasureSpotList){
            spotId2SpotMap.put(treasureSpot.getId(), treasureSpot);
        }

        if(!spotId2SpotMap.containsKey(punchsVo.getTreasureSpotId())){
            return GenericResponse.ng("此景点不可打卡");
        }

        MyTreasureEntity myTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
        MyTreasureEntity insertMyTreasureEntity = null;
        List<Punchs> hasPunchsList = null;
        String myTreasureId = "";
        if(myTreasureEntity == null){
            myTreasureId = idGenerator.nextId();
            insertMyTreasureEntity = new MyTreasureEntity();
            insertMyTreasureEntity.setId(myTreasureId);
            insertMyTreasureEntity.setArActivityId(arActivityId);
            insertMyTreasureEntity.setProviderId(arActivityEntity.getProviderId());
            insertMyTreasureEntity.setUserId(userId);
            insertMyTreasureEntity.setZoneProvince(arActivityEntity.getZoneProvince());
            insertMyTreasureEntity.setZoneCity(arActivityEntity.getZoneCity());
            insertMyTreasureEntity.setZoneDistrict(arActivityEntity.getZoneDistrict());
            insertMyTreasureEntity.setZoneProvinceName(arActivityEntity.getZoneProvinceName());
            insertMyTreasureEntity.setZoneCityName(arActivityEntity.getZoneCityName());
            insertMyTreasureEntity.setZoneDistrictName(arActivityEntity.getZoneDistrictName());
            insertMyTreasureEntity.setProviderName(arActivityEntity.getProviderName());
            myTreasureService.save(insertMyTreasureEntity);
        }else {
            myTreasureId = myTreasureEntity.getId();
            hasPunchsList = myTreasureEntity.getPunchsList();
        }

        if(CollectionUtils.isEmpty(hasPunchsList)){
            hasPunchsList = new ArrayList<>();
        }

        Set<String> hasPunchIdSet = new HashSet<>();
        for(Punchs punchs : hasPunchsList){
            hasPunchIdSet.add(punchs.getTreasureSpotId());
        }
        if(hasPunchIdSet.contains(punchsVo.getTreasureSpotId())){
            return GenericResponse.ng("此景点已打卡");
        }

        TreasureSpot treasureSpot = spotId2SpotMap.get(punchsVo.getTreasureSpotId());
        Punchs punchs = new Punchs();
        punchs.setPunchTime(System.currentTimeMillis());
        punchs.setPhotoUrl(imgUrl);
        punchs.setLongitude(punchsVo.getLongitude());
        punchs.setLatitude(punchsVo.getLatitude());
        punchs.setTreasureSpotId(punchsVo.getTreasureSpotId());
        punchs.setPunchName(treasureSpot.getName());  //设置打卡点名称
        hasPunchsList.add(punchs);
        MyTreasureEntity updateMyTreasureEntity = new MyTreasureEntity();
        updateMyTreasureEntity.setId(myTreasureId);
        updateMyTreasureEntity.setPunchsList(hasPunchsList);
        boolean retFlag = myTreasureService.updateMyTreasureById(updateMyTreasureEntity);
        if(retFlag){
            MyTreasureEntity newMyTreasureEntity = myTreasureService.getByArActivityUserId(arActivityId, userId);
            MyTreasureStatisVo myTreasureStatisVo = new MyTreasureStatisVo();
            List<Punchs> punchsList = newMyTreasureEntity.getPunchsList();
            long totalNum = treasureSpotList==null?0L:treasureSpotList.size();
            long hasNum = punchsList==null?0L:punchsList.size();
            long remainNum = totalNum - hasNum;
            myTreasureStatisVo.setHasNum(hasNum);
            myTreasureStatisVo.setRemainNum(remainNum);
            myTreasureStatisVo.setTreasureImg(arActivityEntity.getTreasureImg());

            return MyTreasureStatisVoResponse.okWithData(myTreasureStatisVo);

        }
        return GenericResponse.ng("打卡失败");
    }

    @ApiOperation(value="我的足迹", notes="我的足迹")
    @ApiResponses({
            @ApiResponse(code = 200, response = MyTreasureResponse.class, message = "我的足迹")
    })
    @GetMapping(value="/mytracks", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> mytracks(HttpServletRequest request) {

        String userId = (String)request.getAttribute("userId");
        List<MyTreasureVo> resultList = new ArrayList<>();

        List<MyTreasureEntity> myTreasureList = myTreasureService.getListByUserId(userId);
        if(CollectionUtils.isNotEmpty(myTreasureList)){
            MyTreasureVo myTreasureVo;
            for(MyTreasureEntity myTreasureEntity : myTreasureList){
                myTreasureVo = new MyTreasureVo();
                BeanUtils.copyProperties(myTreasureEntity, myTreasureVo);

                if(myTreasureVo.getPunchsList() == null){
                    myTreasureVo.setPunchsList(new ArrayList<>(0));
                }

                resultList.add(myTreasureVo);
            }
        }
        return MyTreasureResponse.listNoCount(resultList);
    }


    @ApiOperation(value="添加自定义足迹", notes="添加自定义足迹")
    @ApiResponses({
            @ApiResponse(code = 200, response = GenericResponse.class, message = "添加自定义足迹")
    })
    @PostMapping(value="/footmark", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> addFootMark(HttpServletRequest request,
                                         @ModelAttribute(value = "footMarkVo") @ApiParam(value = "footMarkVo", required = true)FootMarkVo footMarkVo,
                                         @RequestParam(value = "file", required = true) @ApiParam(value = "图片", required = true) MultipartFile file) {

        String userId = (String) request.getAttribute("userId");
        String imgUrl = "";
        try {
            if (file != null && file.getSize()>0) {
                imgUrl = UploadUtil.easyUploadByte(file, QiNiuSpaceEnum.XIAOQ_SITES.getName().toLowerCase(),
                        QiNiuSpaceEnum.XIAOQ_SITES.getDomain());
            }else {
                return GenericResponse.ng("上传的图片为空");
            }
        } catch (Exception e) {
            logger.error("七牛云上传异常！", e);
            return GenericResponse.ng("图片上传失败！");
        }
        if(StringUtils.isBlank(imgUrl)){
            return GenericResponse.ng("1图片上传失败！");
        }

        String id = idGenerator.nextId();
        MyTreasureEntity myTreasure = new MyTreasureEntity();
        BeanUtils.copyProperties(footMarkVo, myTreasure);

        myTreasure.setId(id);
        myTreasure.setPhotoUrl(imgUrl);
        myTreasure.setUserId(userId);
        //myTreasure.setPunchName("青岩古镇");
        //myTreasure.setTreasureSpotId("sites001");
        myTreasure.setPunchTime(System.currentTimeMillis());

        myTreasureService.save(myTreasure);

        return GenericResponse.ok();
    }


    //获取当前位置的最近几公里的数据
    @ApiOperation(value="根据经纬度查询附近的POI信息", notes="根据经纬度查询附近的POI信息")
    @ApiResponses({
            @ApiResponse(code = 200, response = NearAreaResponse.class, message = "根据经纬度查询附近的POI信息")
    })
    @GetMapping(value="/near_area", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> nearLocation(HttpServletRequest request,
                                         @RequestParam(value = "longitude") @ApiParam(value = "经度", required = true)double longitude,
                                         @RequestParam(value = "latitude", required = true) @ApiParam(value = "纬度", required = true) double latitude) {

        long meter = 5000;

        List<NearAreaVo> resultList = new ArrayList<>();
        PagingVo pagingVo = new PagingVo();
        pagingVo.setPn(1);
        pagingVo.setPs(3);
        String userId = (String) request.getAttribute("userId");

        ExecutorService executorService = new ThreadPoolExecutor(3, 3,
                0L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(3));

        List<Future<List<NearAreaVo>>> futureList = new ArrayList<>(3);
        futureList.add(executorService.submit(() -> getNearAreaListFromSites(latitude, longitude, meter, pagingVo)));
        futureList.add(executorService.submit(() -> getNearAreaListFromSitesPoint(latitude, longitude, meter, pagingVo)));
        futureList.add(executorService.submit(() -> getNearAreaListFromShopFood(latitude, longitude, meter, pagingVo)));

        for(Future<List<NearAreaVo>> future : futureList){
            try {
                resultList.addAll(future.get(3, TimeUnit.SECONDS));
            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }
        }
        executorService.shutdown();

        return NearAreaResponse.listNoCount(resultList);
    }

    @ApiOperation(value="搜索景区、景点、必吃", notes="搜索景区、景点、必吃")
    @ApiResponses({
            @ApiResponse(code = 200, response = SearchResultResponse.class, message = "搜索景区、景点、必吃")
    })
    @GetMapping(value="/search/{k}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> search(@PathVariable("k") @ApiParam(value="搜索关键字", required=true) String k,
                    @ApiParam(value="页码,从1开始", required=false) @RequestParam(defaultValue = "1") int pn,
                    @ApiParam(value="条数", required=false) @RequestParam(defaultValue = "5") int ps) {

        if(k==null || StringUtils.isBlank(k.trim())) {
            return GenericResponse.ng("搜索关键字不能为空");
        }
        List<SearchResultVo> resultVoList = new ArrayList<>();

        ExecutorService executorService = new ThreadPoolExecutor(4, 4,
                0L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4));
        pn = (pn - 1) >= 0 ? (pn - 1) : 0;
        PagingVo pagingVo = new PagingVo(pn, ps);

        List<Future<List<SearchResultVo>>> futureList = new ArrayList<>(4);
        futureList.add(executorService.submit(() -> sitesService.findZoneMasterFromEsByName(k, pagingVo)));
        futureList.add(executorService.submit(() -> sitesService.findSitesFromEsByTitle(k, pagingVo)));
        futureList.add(executorService.submit(() -> sitesService.findSitesPointResultFromEsByName(k, pagingVo)));
        futureList.add(executorService.submit(() -> shopFoodService.getShopFoodResultFromEs(k, pagingVo)));

        for(Future<List<SearchResultVo>> future : futureList){
            try {
                resultVoList.addAll(future.get(2, TimeUnit.SECONDS));
            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }
        }

        executorService.shutdown();

        return SearchResultResponse.listNoCount(resultVoList);
    }



    private List<NearAreaVo> getNearAreaListFromSites(double latitude, double longitude, long meter, PagingVo pagingVo){
        List<SitesEntity> sitesList = sitesService.getSitesByPoint(latitude, longitude, meter, pagingVo);
        List<NearAreaVo> resultList = new ArrayList<>();
        NearAreaVo nearAreaVo;
        for (SitesEntity sitesEntity : sitesList){
            if(sitesEntity.getCenterLatitude() != null && sitesEntity.getCenterLatitude() != null){
                nearAreaVo = new NearAreaVo();
                nearAreaVo.setId(sitesEntity.getId());
                nearAreaVo.setLatitude(sitesEntity.getCenterLatitude());
                nearAreaVo.setLongitude(sitesEntity.getCenterLongitude());
                nearAreaVo.setName(sitesEntity.getName());
                nearAreaVo.setType(20);
                resultList.add(nearAreaVo);
            }
        }
        return resultList;
    }

    private List<NearAreaVo> getNearAreaListFromSitesPoint(double latitude, double longitude, long meter, PagingVo pagingVo){
        List<SitesPointEntity> sitesPointList = sitesService.getSitesPointByPoint(latitude, longitude, meter, pagingVo);
        List<NearAreaVo> resultList = new ArrayList<>();
        NearAreaVo nearAreaVo;
        if (CollectionUtils.isNotEmpty(sitesPointList)){
            for (SitesPointEntity sitesPointEntity : sitesPointList){
                if(sitesPointEntity.getLatitude() != null && sitesPointEntity.getLongitude() != null){
                    nearAreaVo = new NearAreaVo();
                    String name = sitesPointEntity.getName();
                    nearAreaVo.setId(sitesPointEntity.getId());
                    nearAreaVo.setLatitude(sitesPointEntity.getLatitude());
                    nearAreaVo.setLongitude(sitesPointEntity.getLongitude());
                    nearAreaVo.setName(name);
                    nearAreaVo.setType(60);
                    resultList.add(nearAreaVo);
                }
            }
        }
        return resultList;
    }

    private List<NearAreaVo> getNearAreaListFromShopFood(double latitude, double longitude, long meter, PagingVo pagingVo){
        List<ShopFoodEntity> shopFoodEntityList = shopFoodService.getShopFoodByPoint(latitude, longitude, meter, pagingVo);
        List<NearAreaVo> resultList = new ArrayList<>();
        NearAreaVo nearAreaVo;
        if(CollectionUtils.isNotEmpty(shopFoodEntityList)){
            for (ShopFoodEntity shopFoodEntity : shopFoodEntityList){
                nearAreaVo = new NearAreaVo();
                nearAreaVo.setId(shopFoodEntity.getId());
                nearAreaVo.setLatitude(shopFoodEntity.getLatitude());
                nearAreaVo.setLongitude(shopFoodEntity.getLongitude());
                nearAreaVo.setName(shopFoodEntity.getName());
                nearAreaVo.setType(70);
                resultList.add(nearAreaVo);
            }
        }
        return resultList;
    }

    public static class MyTreasureStatisVo {
        @ApiModelProperty(name = "hasNum", value = "已捕获的个数", position=0)
        private long hasNum;
        @ApiModelProperty(name = "remainNum", value = "剩余的个数", position=10)
        private long remainNum;
        @ApiModelProperty(name = "treasureImg", value = "宝物图", position=20)
        private String treasureImg;
        public long getHasNum() {
            return hasNum;
        }
        public void setHasNum(long hasNum) {
            this.hasNum = hasNum;
        }
        public long getRemainNum() {
            return remainNum;
        }
        public void setRemainNum(long remainNum) {
            this.remainNum = remainNum;
        }
        public String getTreasureImg() {
            return treasureImg;
        }
        public void setTreasureImg(String treasureImg) {
            this.treasureImg = treasureImg;
        }
    }

}
